package com.coolbi.security.web.oauth;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.coolbi.common.util.Md5Util;
import com.coolbi.security.biz.UserBiz;
import com.coolbi.security.constant.LoginConstant;
import com.coolbi.security.entity.User;

/**
 * @Description 登录验证过滤
 * @author for2cold
 * 
 */
public class MyUsernamePasswordAuthenticationFilter extends
		UsernamePasswordAuthenticationFilter {

	@Autowired
	private UserBiz userBiz;

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {
		if (!request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException(
					"Authentication method not supported: "
							+ request.getMethod());
		}
		// 检测验证码
		checkValidateCode(request);

		String username = obtainUsername(request);
		String password = obtainPassword(request);
		if ("".equals(username) || "".equals(password)) {
			retainFailureMessageInSession("0用户名或密码不能为空!", request);
			throw new AuthenticationServiceException("用户名或密码不能为空!");
		}
		// 验证用户账号与密码是否对应
		username = username.trim();
		User user = userBiz.findUserByUsername(username);

		if (user == null
				|| !user.getPassword().equals(Md5Util.getMD5Str(password))) {
			retainFailureMessageInSession("1用户名或者密码错误！", request);
			throw new AuthenticationServiceException("用户名或者密码错误！");
		}
		if (user.isLock() || !user.isEnable()) {
			retainFailureMessageInSession("2账户不可用或已被锁定！", request);
			throw new AuthenticationServiceException("账户不可用或已被锁定！");
		}
		retainCurrentUserInSession(user, request);
		// UsernamePasswordAuthenticationToken实现 Authentication
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
				username, password);

		// 允许子类设置详细属性
		setDetails(request, authRequest);
		// 运行UserDetailsService的loadUserByUsername 再次封装Authentication
		return this.getAuthenticationManager().authenticate(authRequest);
	}

	protected void checkValidateCode(HttpServletRequest request) {
		HttpSession session = request.getSession();
		String sessionValidateCode = obtainSessionValidateCode(session);
		// 让上一次的验证码失效
		session.setAttribute(LoginConstant.VALIDATE_CODE, null);
		String validateCodeParameter = obtainValidateCodeParameter(request);
		if (StringUtils.isEmpty(validateCodeParameter)
				|| !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {
			retainFailureMessageInSession("3验证码错误", request);
			throw new AuthenticationServiceException("验证码错误！");
		}
	}

	/**将User存放入session中*/
	private void retainCurrentUserInSession(User user, HttpServletRequest request) {
		HttpSession session = request.getSession();
		session.setAttribute(LoginConstant.CURRENT_USER, user);
	}
	
	/**将登录失败信息放入session中*/
	private void retainFailureMessageInSession(String message, HttpServletRequest request) {
		HttpSession session = request.getSession();
		session.setAttribute(LoginConstant.FAILURE_MESSAGE, message);
	}
	
	private String obtainValidateCodeParameter(HttpServletRequest request) {
		Object obj = request.getParameter(LoginConstant.VALIDATE_CODE);
		return null == obj ? "" : obj.toString();
	}

	protected String obtainSessionValidateCode(HttpSession session) {
		Object obj = session.getAttribute(LoginConstant.VALIDATE_CODE);
		return null == obj ? "" : obj.toString();
	}

	@Override
	protected String obtainUsername(HttpServletRequest request) {
		Object obj = request.getParameter(LoginConstant.USERNAME);
		return null == obj ? "" : obj.toString();
	}

	@Override
	protected String obtainPassword(HttpServletRequest request) {
		Object obj = request.getParameter(LoginConstant.PASSWORD);
		return null == obj ? "" : obj.toString();
	}

	public void setUserBiz(UserBiz userBiz) {
		this.userBiz = userBiz;
	}
}
